/*******************************************************************************
* 
* Audio Test
* 
* 
******************************************************************************/
#include "stdafx.h"
#include "CppUnitTest.h"

#include "windows.h"
#include "../common/common.h"

#include <conio.h>
#include "fmod.hpp"
#include "fmod_errors.h"
#ifdef _WIN64
#pragma comment (lib, "fmodex64_vc.lib")
#else
#pragma comment (lib, "fmodex_vc.lib")
#endif


using namespace std;
using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace ut
{
    TEST_CLASS(PlayMusicTest)
    {
    public:

        TEST_METHOD(PlayMusicTestXAudio)
        {
            GloomEngine engine;
            LOG_DEBUG("sizeof(GloomEngine)=%d", sizeof(GloomEngine));

            auto field = engine.resource()->get("sound", "field.wav");
            auto battle = engine.resource()->get("sound", "battle.wav");

            auto field_asp = engine.audio()->create(*field.get());
            auto battle_asp = engine.audio()->create(*battle.get());

            // play backgound sound async
            field_asp->play();

            Sleep(2000); // 2

            // play sound effect async
            battle_asp->play();

            Sleep(10000); // 8 + 2

            // play sound effect synchronized
            battle_asp->play(false);

            // stop the sound immediately.
            battle_asp->stop();
            field_asp->stop();

            // release the resource.
            field_asp.reset();
            battle_asp.reset();

            // TODO:
            //GloomEngine::instance()->font()->register(L"msyh.ttc");
            //GloomEngine::instance()->font()->unregister(L"msyh.ttc");
            //GloomEngine::instance()->graphic()->loadfont(L"Microsoft YaHei");
            //GloomEngine::instance()->graphic()->begin();
            //GloomEngine::instance()->graphic()->end();
            //GloomEngine::instance()->graphic()->flip();
            //GloomEngine::instance()->graphic()->draw();
        }

        void ERRCHECK(FMOD_RESULT result)
        {
            if (result != FMOD_OK)
            {
                printf("FMOD error! (%d) %s\n", result, FMOD_ErrorString(result));
                exit(-1);
            }
        }

        TEST_METHOD(PlayMusicTestFMod)
        {
            FMOD::System     *system;
            FMOD::Sound      *sound1, *sound2, *sound3;
            FMOD::Channel    *channel = 0;
            FMOD_RESULT       result;
            int               key;
            unsigned int      version;

            /*
            Create a System object and initialize.
            */
            result = FMOD::System_Create(&system);
            ERRCHECK(result);

            result = system->getVersion(&version);
            ERRCHECK(result);

            if (version < FMOD_VERSION)
            {
                //printf("Error!  You are using an old version of FMOD %08x.  This program requires %08x\n", version, FMOD_VERSION);
                LOG_FATAL("Error!  You are using an old version of FMOD %08x.  This program requires %08x\n", version, FMOD_VERSION);
                return;
            }

            result = system->init(32, FMOD_INIT_NORMAL, 0);
            ERRCHECK(result);

            auto data = FileHelper::readAll("d:/Lady GaGa - Poker Face.mp3");
            FMOD_CREATESOUNDEXINFO si = {0};
            {
                si.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
                si.length = data->size();
            }
            result = system->createSound((const char*)&(*data.get())[0], FMOD_HARDWARE | FMOD_OPENMEMORY | FMOD_CREATECOMPRESSEDSAMPLE, &si, &sound1);
            ERRCHECK(result);

            //result = sound1->setMode(FMOD_LOOP_OFF);    /* drumloop.wav has embedded loop points which automatically makes looping turn on, */
            //ERRCHECK(result);                           /* so turn it off here.  We could have also just put FMOD_LOOP_OFF in the above CreateSound call. */

            //result = system->createSound("d:/battle.wav", FMOD_SOFTWARE, 0, &sound2);
            //ERRCHECK(result);

            //result = system->createSound("d:/intro.wav", FMOD_HARDWARE, 0, &sound3);
            //ERRCHECK(result);

            //printf("===================================================================\n");
            //printf("PlaySound Example.  Copyright (c) Firelight Technologies 2004-2011.\n");
            //printf("===================================================================\n");
            //printf("\n");
            //printf("Press '1' to play a mono sound using hardware mixing\n");
            //printf("Press '2' to play a mono sound using software mixing\n");
            //printf("Press '3' to play a stereo sound using hardware mixing\n");
            //printf("Press 'Esc' to quit\n");
            //printf("\n");

            /*
            Main loop.
            */
            {
                result = system->playSound(FMOD_CHANNEL_FREE, sound1, false, &channel);
                ERRCHECK(result);
                //break;
            }

            do
            {
            //    if (_kbhit())
            //    {
            //        key = _getch();

            //        switch (key)
            //        {
            //        case '1' :
                       /* {
                            result = system->playSound(FMOD_CHANNEL_FREE, sound1, false, &channel);
                            ERRCHECK(result);
                            break;
                        }*/
                //    case '2' :
                //        {
                //            result = system->playSound(FMOD_CHANNEL_FREE, sound2, false, &channel);
                //            ERRCHECK(result);
                //            break;
                //        }
                //    case '3' :
                //        {
                //            result = system->playSound(FMOD_CHANNEL_FREE, sound3, false, &channel);
                //            ERRCHECK(result);
                //            break;
                //        }
                //    }
                //}

                system->update();

                {
                    unsigned int ms = 0;
                    unsigned int lenms = 0;
                    bool         playing = 0;
                    bool         paused = 0;
                    int          channelsplaying = 0;

                    if (channel)
                    {
                        FMOD::Sound *currentsound = 0;

                        result = channel->isPlaying(&playing);
                        if ((result != FMOD_OK) && (result != FMOD_ERR_INVALID_HANDLE) && (result != FMOD_ERR_CHANNEL_STOLEN))
                        {
                            ERRCHECK(result);
                        }

                        result = channel->getPaused(&paused);
                        if ((result != FMOD_OK) && (result != FMOD_ERR_INVALID_HANDLE) && (result != FMOD_ERR_CHANNEL_STOLEN))
                        {
                            ERRCHECK(result);
                        }

                        result = channel->getPosition(&ms, FMOD_TIMEUNIT_MS);
                        if ((result != FMOD_OK) && (result != FMOD_ERR_INVALID_HANDLE) && (result != FMOD_ERR_CHANNEL_STOLEN))
                        {
                            ERRCHECK(result);
                        }

                        channel->getCurrentSound(&currentsound);
                        if (currentsound)
                        {
                            result = currentsound->getLength(&lenms, FMOD_TIMEUNIT_MS);
                            if ((result != FMOD_OK) && (result != FMOD_ERR_INVALID_HANDLE) && (result != FMOD_ERR_CHANNEL_STOLEN))
                            {
                                ERRCHECK(result);
                            }
                        }
                    }

                    system->getChannelsPlaying(&channelsplaying);

                    //LOG_DEBUG("Time %02d:%02d:%02d/%02d:%02d:%02d : %s : Channels Playing %2d\r", ms / 1000 / 60, ms / 1000 % 60, ms / 10 % 100, lenms / 1000 / 60, lenms / 1000 % 60, lenms / 10 % 100, paused ? "Paused " : playing ? "Playing" : "Stopped", channelsplaying);
                }

                Sleep(10);

            } while (true);

            //printf("\n");

            /*
            Shut down
            */
            result = sound1->release();
            ERRCHECK(result);
            //result = sound2->release();
            //ERRCHECK(result);
            //result = sound3->release();
            //ERRCHECK(result);
            result = system->close();
            ERRCHECK(result);
            result = system->release();
            ERRCHECK(result);

        }

    };
}